<?php

/**
 * 缓存抽象类
 */
abstract class Cache {

    /**
     * 静态单例对象
     * @var obj 
     */
    protected static $_instance = null;

    /**
     * 静态本地储存数组
     * @var array 
     */
    protected static $_local = array();

    /**
     * 静态配置变量
     * @var array 
     */
    public static $options = array();

    /**
     * 设置缓存数据抽象方法
     */
    abstract protected function _set($key, $value, $ttl = 0);

    /**
     * 读取缓存数据抽象方法
     */
    abstract protected function _get($key);

    /**
     * 删除缓存数据抽象方法
     */
    abstract protected function _delete($key);

    /**
     * 判断缓存数据是否存在抽象方法
     */
    abstract protected function _exist($key);

    /**
     * 清空缓存数据抽象方法
     */
    abstract protected function _clean();

    /**
     * 缓存状态数据抽象方法
     */
    abstract protected function _stats();

    /**
     * 单例方法
     * @return Cache
     */
    public static function getInstance() {
        if (null === self::$_instance) {
            self::$options = Yaf_Registry::get('config')->cache->toArray();
            $driver = "Cache_" . self::$options['firstdriver'];
            $name = strtolower(self::$options['firstdriver']);
            if (!$driver::checkDriver(Yaf_Registry::get('config')->cache->$name)) {
                $driver = "Cache_" . self::$options['seconddriver'];
                $name = strtolower(self::$options['seconddriver']);
            }
            self::$options['driver'] = $name;
            self::$_instance = new $driver();
        }
        return self::$_instance;
    }

    /**
     * 读取或设置属性
     * @param string $key 属性名
     * @param mixed $value 属性值,为空时则为读取
     * @return mixed 
     */
    public static function options($key, $value = NULL) {
        if (is_null($value)) {
            if (is_array($key)) {
                self::$options = Tools::arrayMultiMerge(self::$options, $key);
                return $key;
            } else {
                return isset(self::$options[$key]) ? self::$options[$key] : NULL;
            }
        } else {
            self::$options[$key] = $value;
            return self::$options[$key];
        }
    }

    /**
     * 魔术get方法
     * @param string $key
     * @return mixed
     */
    public function __get($key) {
        return $this->get($key);
    }

    /**
     * 魔术set方法
     * @param string $key
     * @param mixed $value
     * @return mixed
     */
    public function __set($key, $value) {
        return $this->set($key, $value);
    }

    /**
     * 缓存编码
     * @param mixed $data
     * @return string
     */
    public function encode($data) {
        //json_encode,serialize,msgpack_pack
        return serialize($data);
    }

    /**
     * 缓存解码
     * @param mixed $value
     * @return mixed
     */
    public function decode($value) {
        //json_decode,unserialize,msgpack_unpack
        $x = @unserialize($value);
        if ($x == false) {
            return $value;
        } else {
            return $x;
        }
    }

    /**
     * 设置缓存
     * @param string $key
     * @param mixed $value
     * @param int $ttl 缓存生存时长
     * @return mixed
     */
    public function set($key, $value, $ttl = 0) {
        $key = $this->getKeyName($key);
        $object = array(
            "value" => $value,
            "write_time" => time(),
            "expired_in" => (int) $ttl,
            "expired_time" => time() + (int) $ttl,
        );
        return $this->_set($key, $object, $ttl);
    }

    /**
     * 读取缓存
     * @param string $key
     * @return mixed
     */
    public function get($key) {
        $key = $this->getKeyName($key);
        $object = $this->_get($key);
        if ($object == null) {
            return null;
        }
        return isset($object['value']) ? $object['value'] : null;
    }

    /**
     * 删除缓存
     * @param string $key
     * @return mixed
     */
    public function delete($key) {
        $key = $this->getKeyName($key);
        $this->_delete($key);
    }

    /**
     * 判断缓存是否存在
     * @param string $key
     * @return mixed
     */
    public function exist($key) {
        $key = $this->getKeyName($key);
        $this->_exist($key);
    }

    /**
     * 清空缓存
     * @return mixed
     */
    public function clean() {
        $this->_clean();
    }

    /**
     * 缓存数据状态
     * @return mixed
     */
    public function stats() {
        return $this->_stats();
    }

    /**
     * 获取键名
     * @param string $key
     * @return string
     */
    public function getKeyName($key) {
        return self::options('driver') == 'redis' ? $key : self::$options['prefix'] . $key;
    }

    /**
     * 存储临时变量缓存
     * @param string $key
     * @param mixed $value
     */
    public static function store($key, $value) {
        Cache::$_local[$key] = $value;
    }

    /**
     * 读取临时变量缓存
     * @param string $key
     * @return mixed
     */
    public static function retrieve($key) {
        return isset(Cache::$_local[$key]) ? Cache::$_local[$key] : null;
    }

    /**
     * 返回所有临时变量缓存
     * @return array
     */
    public static function retrieveAll() {
        return Cache::$_local;
    }

    /**
     * 清空临时变量缓存
     * @param string $key
     */
    public static function flush($key) {
        if (strpos($key, '*') !== false) {
            $regexp = str_replace('\\*', '.*', preg_quote($key, '#'));
            foreach (array_keys(Cache::$_local) as $key)
                if (preg_match('#^' . $regexp . '$#', $key))
                    unset(Cache::$_local[$key]);
        } else
            unset(Cache::$_local[$key]);
    }

}
